package com.qf.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @date 2025/4/30
 * @desc
 */
@Component
public class JwtUtils {
    // 密钥
    // 令牌自定义标识
    @Value("${token.header}")
    private String header;

    // 令牌秘钥
    @Value("${token.secret}")
    private String secret;

    // 令牌有效期（默认30分钟）
    @Value("${token.expireTime}")
    private int expireTime;

    @Autowired
    private RedisUtil redisUtil;

    /**
     * 生成jwt
     *
     * @param claims
     * @return
     */
    public String createJwt(Map<String, Object> claims) {
        String uuid = UUID.randomUUID( ).toString( ).replace( "-", "" );
        claims.put("uuid", uuid);

        // 签名算法，表示sha256
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

        //构造jwt
        JwtBuilder builder = Jwts.builder( )//.setHeaderParam("type","jwt") // 设置头
                .setClaims(claims) // 设置载荷
                .signWith(signatureAlgorithm, secret); // 使用指定算法设置签名
        //生成jwt
        String token = builder.compact( );

        // 保存到redis
        redisUtil.setCacheObject("user:key:"+uuid,token,expireTime, TimeUnit.MINUTES);
        return token;
    }

    /**
     * 解析，如果不符合，报异常
     *
     * @param jsonWebToken
     * @return
     */
    public Claims parseJWT(String jsonWebToken) {
        try {
            Claims claims = Jwts.parser( )
                    .setSigningKey(secret)
                    .parseClaimsJws(jsonWebToken).getBody( );
            return claims;
        } catch (Exception ex) {
            throw new RuntimeException(ex.getMessage( ));
        }
    }

    public String getToken(HttpServletRequest request) {
        String token = request.getHeader(header);
        if (StringUtils.hasText(token)) {
            return token;
        }
        return null;
    }


    /**
     * 验证token, 验证此次请求有没有超时
     */
    public void validateToken(String token) {
        Claims claims = Jwts.parser( )
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody( );
        Object uuid = claims.get("uuid");
        Object redisToken = redisUtil.getCacheObject("user:key:" + uuid);
        if (redisToken == null || !redisToken.equals(token)) {
            throw new AccessDeniedException("token验证失败");
        }
    }

    public void refreshToken(String token) {
        Claims claims = Jwts.parser( )
                .setSigningKey(secret)
                .parseClaimsJws(token).getBody( );
        Object uuid = claims.get("uuid");
        // 保存到redis
        redisUtil.setCacheObject("user:key:"+uuid,token,expireTime, TimeUnit.MINUTES);
    }
}
